import cv2  
import numpy as np  
import os  
import matplotlib.pyplot as plt  
  
# 设置字体和负号显示  
plt.rcParams['font.sans-serif'] = ['SimHei']  
plt.rcParams['axes.unicode_minus'] = False  
  
# 读取图像  
img = cv2.imread('hanzi1.jpg')  
  
# 转换为灰度图像  
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  
  
# 二值化图像  
_, binary_image = cv2.threshold(gray_image, 70, 255, cv2.THRESH_BINARY_INV)  
  
# 定义腐蚀操作的核  
kernel = np.ones((4, 4), np.uint8)  
eroded_image = cv2.erode(binary_image, kernel, iterations=2)  
  
# 定义膨胀操作的核
kernel1 = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5)).astype(np.uint8)  
dilated_image = cv2.dilate(eroded_image, kernel1)  
  
# 中值滤波  
median_img = cv2.medianBlur(dilated_image, 5)  
  
# 定义闭操作的核  
kernel2 = np.ones((10, 10), np.uint8)  
closing_image = cv2.morphologyEx(median_img, cv2.MORPH_CLOSE, kernel2, iterations=7)  
  
# Canny边缘检测的参数  
lower = 50  
upper = 200  
  
# 高斯滤波  
img_blur = cv2.GaussianBlur(img, (3, 3), 0)  
  
# Canny边缘检测  
edges_with_blur = cv2.Canny(closing_image, lower, upper)  
  
# 查找轮廓  
contours, _ = cv2.findContours(edges_with_blur, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)  
  
# 初始化结果图像  
result_img = np.zeros_like(edges_with_blur)  
result = img.copy()  
  
# 字符图像保存目录  
chars_dir = 'chars'  
count = 1  
  
# 如果目录不存在，则创建  
if not os.path.exists(chars_dir):  
    os.makedirs(chars_dir)  
  
# 遍历轮廓  
for c in contours:  
    perimeter = cv2.arcLength(c, True)  
    x, y, w, h = cv2.boundingRect(c)  
    cv2.rectangle(result_img, (x, y), (x + w, y + h), (255), 2)  
    if perimeter > 100:  
        cv2.rectangle(result, (x, y), (x + w, y + h), (0, 255, 0), 2)  
        char_img = img[y:y + h, x:x + w]  
        char_filename = os.path.join(chars_dir, f'{count}.png')  
        cv2.imwrite(char_filename, char_img)  
        count += 1  
  
# 绘制并显示图像  
fig, ax = plt.subplots(1, 7, figsize=(20, 10))  
ax[0].imshow(gray_image, cmap='gray')  
ax[0].set_title("原图灰度图", size=6)  
ax[0].axis('off')  
ax[1].imshow(binary_image, cmap='gray')  
ax[1].set_title("全局阈值处理，二值化图", size=6)  
ax[1].axis('off')  
ax[2].imshow(eroded_image, cmap='gray')  
ax[2].set_title("应用腐蚀操作，去除噪点", size=6)  
ax[2].axis('off')  
ax[3].imshow(dilated_image, cmap='gray')  
ax[3].set_title("应用膨胀操作，中值滤波去除小白点", size=6)  
ax[3].axis('off')  
  
ax[4].imshow(closing_image, cmap='gray')  
ax[4].set_title("应用闭运算，填充闭合区域", size=6)  
ax[4].axis('off')  
  
ax[5].imshow(edges_with_blur, cmap='gray')  
ax[5].set_title("Canny边缘检测", size=6)  
ax[5].axis('off')  
  
ax[6].imshow(result, cmap='gray') 
ax[6].set_title("识别结果", size=6)  
ax[6].axis('off')  
  
plt.tight_layout()  
fig.savefig('hanzi.png', dpi=300, bbox_inches='tight')  
plt.show()